<?php

namespace App\Http\Models;

use App\Traits\ApiResponse;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\Paginator;
use Watson\Rememberable\Rememberable;

class BaseModel extends Model
{
    use ApiResponse;
    use Rememberable;
    // public $timestamps = false;
    //重写分页方法，使其更加匹配API的规范
    //考虑到性能问题，通常$columns我们不以*号为值。可传入需要查询的字段替代。这里只做演示。无此要求
    /**
     * 分页
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-03
     * @param int $page 当前页
     * @param int $perPage 每页条数
     * @param array $columns
     * @param string $pageName
     * @param string $cache
     * @return mixed
     */
    public function paginate($page = null, $perPage = null, $where = [], $columns = ['*'], $orderBy = 'desc',  $pageName = 'page', $cache = '')
    {

        $page = $page ?: Paginator::resolveCurrentPage($pageName);

        $perPage = $perPage ?: $this->getPerPage();

        if (!empty($cache)) {

            $results =  $this->forPage($page, $perPage)->remember($cache)->where($where)->orderBy('id', $orderBy)->get($columns);
            $total = $this->where($where)->remember($cache)->count();
        } else {
            $results =  $this->forPage($page, $perPage)->where($where)->orderBy('id', $orderBy)->get($columns);
            $total = $this->where($where)->count();
        }

        $results = self::_unsetNull($results->toArray());

        $pages = ceil($total / $perPage);

        $result = ['total' => $total, 'current_page' => $page, 'page_size' => $perPage, 'pages' => $pages, 'list' => $results];
        return $result;
    }

    /**
     * 分页
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-03
     * @param int $page 当前页
     * @param int $perPage 每页条数
     * @param array $columns
     * @param string $pageName
     * @return mixed
     */
    public function paginateReturnModel($page = null, $perPage = null, $where = [], $columns = ['*'], $orderBy = 'desc',  $pageName = 'page', $cache = '')
    {

        $page = $page ?: Paginator::resolveCurrentPage($pageName);

        $perPage = $perPage ?: $this->getPerPage();

        if (!empty($cache)) {

            $results =  $this->forPage($page, $perPage)->remember($cache)->where($where)->orderBy('id', $orderBy)->get($columns);
            $total = $this->where($where)->remember($cache)->count();
        } else {
            $results =  $this->forPage($page, $perPage)->where($where)->orderBy('id', $orderBy)->get($columns);
            $total = $this->where($where)->count();
        }

        $pages = ceil($total / $perPage);

        $result = ['total' => $total, 'current_page' => $page, 'page_size' => $perPage, 'pages' => $pages, 'list' => $results];
        return $result;
    }

    /**
     * 软删除
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-09
     * @param array $where
     * @return mixed
     */
    public static function delOneSoft($where)
    {
        $model = self::where($where)->first();
        if (empty($model)) {
            return [];
        }
        $model->is_del = 1;
        return $model->save();
    }

    /**
     * 获取详情
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-09
     * @param array $where
     * @param array $field
     * @return mixed
     */
    public static function getOne($where, $field = ['*'], $cache = '')
    {
        $info = self::where($where)->select($field)->remember($cache)->first();

        if (empty($info)) {
            return [];
        }

        return self::_unsetNull($info->toArray());
    }


    /**
     * 异步设置项目字段值
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-10
     * @param int $project_id
     * @param string $field
     * @param array $setvalue
     * @return mixed
     */
    public static function setFiledValues($project_id, $field, $setvalue, $memberId)
    {
        $project_info = Project::find($project_id);
        if (!empty($project_info)) {
            if ($project_info->user_id != $memberId) {
                return fail_message('您无法操作该项目,如需添加信息，请到对应信息库添加');
            }
        }
        return self::create([
            'project_id' => $project_id,
            $field => $setvalue,
            'user_id' => $memberId,
        ]);
    }

    /**
     * 异步修改字段值
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-10
     * @param array $values  需要修改的数组 例如：[['project_id'=>'flowerhua','expert_id'=>10],['project_id'=>'flowerhua2','expert_id'=>20]]
     * @param array $uniqueBy 根据哪个字段修改  例如：['project_id','expert_id']
     * @param array $updateFiled 需要修改的字段  例如：['expert_id']
     * @return void
     */
    public static function setSyncExpertValues($values, $uniqueBy, $updateFiled)
    {
        return self::upsert($values, $uniqueBy, $updateFiled);
    }


    /**
     * 高精度 加法
     * @param int|string $uid id
     * @param string $incField 相加的字段
     * @param float|int $inc 加的值
     * @param string $keyField id的字段
     * @param int $acc 精度
     * @return bool
     */
    public static function bcInc($key, $incField, $inc, $keyField = null, $acc = 2)
    {
        if (!is_numeric($inc)) return false;
        $model = new self();
        if ($keyField === null) $keyField = $model->getKey();
        $result = self::where($keyField, $key)->first();
        if (!$result) return false;
        $new = bcadd($result[$incField], $inc, $acc);
        $result->$incField = $new;
        return false !== $result->save();
    }


    /**
     * 高精度 减法
     * @param int|string $uid id
     * @param string $decField 相减的字段
     * @param float|int $dec 减的值
     * @param string $keyField id的字段
     * @param bool $minus 是否可以为负数
     * @param int $acc 精度
     * @return bool
     */
    public static function bcDec($key, $decField, $dec, $keyField = null, $minus = false, $acc = 2)
    {
        if (!is_numeric($dec)) return false;
        $model = new self();
        if ($keyField === null) $keyField = $model->getKey();
        $result = self::where($keyField, $key)->first();
        if (!$result) return false;
        if (!$minus && $result[$decField] < $dec) return false;
        $new = bcsub($result[$decField], $dec, $acc);
        $result->$decField = $new;
        return false !== $result->save();
    }


    /**
     * 删除各个project关联表信息
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-15
     * @param [type] $id  int string array collect
     * @return mixed
     */
    public static function deleteProjectId($payload, $key)
    {
        return self::where('project_id', $payload['project_id'])->where($key, $payload['id'])->delete();
    }

    /**
     * 新建、修改project相关表操作
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-03-15
     * @param array $where
     * @param array $data
     * @return mixed
     */
    public static function projectCreate($payload, $key)
    {

        return self::create([
            'project_id' => $payload['project_id'],
            $key => $payload['id'],
            'user_id' => memberId(),
        ]);
    }

    /**
     * 判断地址是否是url地址
     *
     * @Author hechengwei
     * @email chichiooo@sina.com
     * @DateTime 2022-04-11
     * @param string $url
     * @return bool
     */
    public function or_url($url)
    {

        if (empty($url)) {
            return true;
        }
        $preg = "/http[s]?:\/\/[\w.]+[\w\/]*[\w.]*\??[\w=&\+\%]*/is";

        if (preg_match($preg, $url)) {

            return true;
        } else {

            return false;
        }
    }

    protected $data;

    protected function setData($key, $value)
    {
        $this->data[$key] = $value;
        array_walk_recursive($this->data, function (&$item, $key) {
            $item = null === $item ? '' : $item;
        });
        return $this->data;
    }

    //递归方式把数组或字符串 null转换为空''字符串
    public static function _unsetNull($arr)
    {

        if ($arr !== null) {
            if (is_array($arr)) {
                if (!empty($arr)) {
                    foreach ($arr as $key => $value) {
                        if ($value === null) {
                            $arr[$key] = '';
                        } else {
                            $arr[$key] = self::_unsetNull($value);      //递归再去执行
                        }
                    }
                }
            } else {

                if ($arr === null) {
                    $arr = '';
                }         //注意三个等号
            }
        } else {
            $arr = '';
        }

        return $arr;
    }
}
